#ifndef _QUAD_TREE_MANAGER_
#define _QUAD_TREE_MANAGER_

#include "FEngineType.h"
#include "AABB.h"
#include <list>

namespace FEngine
{
	class QuadTreeNode;

	/**
	 * A Quad tree is a tree structure where each node has four children.
	 * A node represent a 2D area, and each child node takes place in
	 * one of the four sub-area of the parent node.
	 * The template is used to pass the type of object each node will handle.
	 */
	class QuadTreeManager
	{

		public:
			
			static enum SquarePosition
			{
				SQUARE_LEFT_BOTTOM = 0,
				SQUARE_LEFT_TOP,
				SQUARE_RIGHT_TOP,
				SQUARE_RIGHT_BOTTOM,

				SQUARE_OUTSIDE,
			};

			/**
			 * Constructor.
			 * @param _float Minimum size of the smaller nodes.
			 */
			QuadTreeManager(float _size);
			~QuadTreeManager();

			/**
			 * Return the node containing the given position.
			 * If the node doesn't exist, create it.
			 * @param _pos Position contained in the node we are looking for.
			 * @param _nodeToCreate If the node does not exist, add this one instead. This node is deleted if needed, dont use it.
			 * @return The node that contains the given position.
			 */
			QuadTreeNode* getNodeByPosition(const Vector2& _pos, QuadTreeNode* _nodeToCreate);

			/**
			 * Return the four child nodes of the tree.
			 * @return List of node.
			 */
			std::list<QuadTreeNode*> getChildNode() const;

			/**
			 * Return the limits of the whole tree.
			 * @return The AABB of the tree.
			 */
			AABB* getAABB() const;

			/**
			 * Return the minimum size of one node.
			 * @return Size of the node.
			 */
			float getMinimumSize() const;
			
			/**
			 * Check the visibility of every node of the tree.
			 */
			void checkVisibility(float _maxView = -1.0f);
			
			/**
			 * Return the list of nodes (inversed deep = 0).
			 * @return List of the nodes.
			 */
			std::list<QuadTreeNode*> getNodes() const;

			/**
			 * Return the list of visible nodes (inversed deep = 0).
			 * @return List of the visible nodes.
			 */
			std::list<QuadTreeNode*> getVisibleNodes() const;
			
			/**
			 * Return the number of visible nodes (inversed deep = 0).
			 * @return Number of visible nodes.
			 */
			int getNumberNodes() const;
			
			/**
			 * Return the number of visible nodes (inversed deep = 0).
			 * @return Number of visible nodes.
			 */
			int getNumberVisibleNodes() const;
			

			void _getListNodes();

		private:

			AABB*						mAABB;
			float						mMinimumSize;

			QuadTreeNode*				mChildNode[4];
			std::list<QuadTreeNode*>	mListVisibleNodes;
			std::list<QuadTreeNode*>	mListNodes;

			
			void _calulateAABB();
};

} // namespace FEngine

#endif
